package com.lxy.gateway.filter;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 123
 * @date 2020/6/29 23:05
 * @description
 */
@Component
@Slf4j
public class IpFilter implements GlobalFilter, Ordered {

    @Value("${ip.filter.x:1}")
    private Integer minutes;
    @Value("${ip.filter.y:10}")
    private Integer times;

    //
    Map<String, List<Long>> clientRegisterMap=new ConcurrentHashMap();



    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        // 从上下文中取出request和response对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String path = request.getURI().getPath();
        //请求注册接口
        if(path.contains("/user/register")){
            String hostAddress = request.getRemoteAddress().getHostString();
            if(clientRegisterMap.get(hostAddress)==null){
                clientRegisterMap.put(hostAddress,new ArrayList<>());
            }
            List<Long> requestRegisterApiStamptimeList = clientRegisterMap.get(hostAddress);
            long intervalMinutes = DateUtils.addMinutes(new Date(),-minutes).getTime();
            // 计算单位时间内的请求次数
            long count = requestRegisterApiStamptimeList.stream().filter(time -> time > intervalMinutes).count();
            // 请求次数大于上限
            if(count>times){
                // 决绝访问，返回
                response.setStatusCode(HttpStatus.UNAUTHORIZED); // 状态码
                String message="=====>IP:" + hostAddress + " "+minutes+"分钟内请求注册接口"+count+"次，大于限制次数："+times;
                log.debug(message);
                DataBuffer wrap = response.bufferFactory().wrap(message.getBytes());
                return response.writeWith(Mono.just(wrap));
            }
            // 保存本次请求时间戳
            requestRegisterApiStamptimeList.add(System.currentTimeMillis());
        }

        // 合法请求，放行，执行后续的过滤器
        return chain.filter(exchange);

    }


    @Override
    public int getOrder() {
        return 2;
    }

    public static void main(String[] args) {
        long time = DateUtils.addMinutes(new Date(), -1).getTime();
        System.out.println(new Date(time));
    }
}
